package db4oServer;

import com.db4o.ObjectContainer;
import com.db4o.ObjectServer;
import com.db4o.cs.Db4oClientServer;
import com.db4o.cs.config.ServerConfiguration;
import com.db4o.messaging.MessageContext;
import com.db4o.messaging.MessageRecipient;

/** *//**
 * starts a db4o server with the settings from {@link ServerSetup}. <br>
 * <br>
 * This is a typical setup for a long running server. <br>
 * <br>
 * The Server may be stopped from a remote location by running StopServer. The
 * StartServer instance is used as a MessageRecipient and reacts to receiving an
 * instance of a StopServer object. <br>
 * <br>
 * Note that all user classes need to be present on the server side and that all
 * possible Db4oEmbedded.configure() calls to alter the db4o configuration need
 * to be executed on the client and on the server.
 */
public class StartServer implements ServerSetup, MessageRecipient  {

  /** *//**
   * setting the value to true denotes that the server should be closed
   */
  private boolean stop = false;

  public boolean isStop() {
	return stop;
}

/** *//**
   * starts a db4o server using the configuration from
   * {@link ServerSetup}.
   */
  public static void main(String[] arguments)  {
    new StartServer().runServer();
  }

  // end main

  /** *//**
   * opens the ObjectServer, and waits forever until close() is called or a
   * StopServer message is being received.
   */
  public void runServer()  {
    synchronized (this)  {
      // Using the messaging functionality to redirect all
      // messages to this.processMessage
      ServerConfiguration config = Db4oClientServer.newServerConfiguration();
      config.networking().messageRecipient(this);

      ObjectServer db4oServer = Db4oClientServer.openServer(
          config, FILE, PORT);
      db4oServer.grantAccess(USER, PASS);

      
      // to identify the thread in a debugger
      Thread.currentThread().setName(this.getClass().getName());

      // We only need low priority since the db4o server has
      // it's own thread.
      Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
      try  {
        if (!stop)  {
          // wait forever for notify() from close()
          this.wait(Long.MAX_VALUE);
        }
      } catch (Exception e)  {
        e.printStackTrace();
      }
      db4oServer.close();
    }
  }

  // end runServer

  /** *//**
   * messaging callback
   * 
   * @see com.db4o.messaging.MessageRecipient#processMessage(ObjectContainer,
   *      Object)
   */
  public void processMessage(MessageContext context, Object message)  {
    if (message instanceof StopServer)  {
      close();
    }
  }

  // end processMessage

  /** *//**
   * closes this server.
   */
  public void close()  {
    synchronized (this)  {
      stop = true;
      this.notify();
    }
  }
  // end close
}
